#include <unistd.h>
#include <pthread.h>

#include "log.h"

#include "LuaJavaHelper.h"

void jni_openLibs(JNIEnv *env, jobject jobj) {
    LOGV("call jni_openLibs");
    LuaJavaHelper::getInstance()->openLibs();
}

void jni_closeLibs(JNIEnv *env, jobject jobj) {
    LOGV("call jni_closeLibs");
    LuaJavaHelper::getInstance()->closeLibs();
}

void jni_setPackagePath(JNIEnv *env, jobject jobj, jstring jpath) {
    LOGV("call jni_setPackagePath");
    LuaJavaHelper::getInstance()->setPackagePath(env, jpath);
}

void jni_setPackageCPath(JNIEnv *env, jobject jobj, jstring jcpath) {
    LOGV("call jni_setPackageCPath");
    LuaJavaHelper::getInstance()->setPackageCPath(env, jcpath);
}

void jni_setCallback(JNIEnv *env, jobject jobj, jobject jcallback) {
    LOGV("call jni_setCallback");
    LuaJavaHelper::getInstance()->setCallbackObj(jcallback);
}

jint jni_doFile(JNIEnv *env, jobject jobj, jstring jfilepath) {
    LOGV("call jni_doFile");
    return LuaJavaHelper::getInstance()->doFile(env, jobj, jfilepath);
}

jint jni_doString(JNIEnv *env, jobject jobj, jstring jstr) {
    LOGV("call jni_doString");
    return LuaJavaHelper::getInstance()->doString(env, jobj, jstr);
}

void jni_doStop(JNIEnv *env, jobject jobj) {
    LOGV("call jni_doStop");
    LuaJavaHelper::getInstance()->stop();
}

void jni_sendEvent(JNIEnv *env, jobject jobj, jstring jid, jint jaction, jint jfunID) {
    LOGV("call jni_sendEvent");
    LuaJavaHelper::getInstance()->sendEvent(env, jobj, jid, jaction, jfunID);
}

void jni_removeActionCallback(JNIEnv *env, jobject jobj, jint jaction, jint jfunID) {
    LOGV("call jni_removeActionCallback");
    LuaJavaHelper::getInstance()->removeActionCallback(env, jobj, jaction, jfunID);
}

static const JNINativeMethod jni_methods[] = {
        {"nativeOpenLibs",             "()V",                     (void *) jni_openLibs},
        {"nativeCloseLibs",            "()V",                     (void *) jni_closeLibs},
        {"nativeSetPackagePath",       "(Ljava/lang/String;)V",   (void *) jni_setPackagePath},
        {"nativeSetPackageCPath",      "(Ljava/lang/String;)V",   (void *) jni_setPackageCPath},
        {"nativeSetCallback",          "(Ljava/lang/Object;)V",   (void *) jni_setCallback},
        {"nativeDoFile",               "(Ljava/lang/String;)I",   (void *) jni_doFile},
        {"nativeDoString",             "(Ljava/lang/String;)I",   (void *) jni_doString},
        {"nativeDoStop",               "()V",                     (void *) jni_doStop},
        {"nativeSendEvent",            "(Ljava/lang/String;II)V", (void *) jni_sendEvent},
        {"nativeRemoveActionCallback", "(II)V",                   (void *) jni_removeActionCallback},
};

JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    LOGV("JNI_OnLoad");

    JNIEnv *env = nullptr;

    if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
        LOGE("get env failed")
        return JNI_ERR;
    }

    jclass cls = env->FindClass(CLASS_NAME_LUAJAVA);
    if (cls == nullptr) {
        LOGE("get luajava class failed")
        return JNI_ERR;
    }

    int nMethods = sizeof(jni_methods) / sizeof(jni_methods[0]);
    LOGV("methods len:%d", nMethods);

    if (env->RegisterNatives(cls, jni_methods, nMethods) < 0) {
        LOGE("register methods failed")
        return JNI_ERR;
    }

    LuaJavaHelper::getInstance()->onLoad(vm);

    LOGI("load success");
    return JNI_VERSION_1_4;
}

JNIEXPORT void JNI_OnUnload(JavaVM *vm, void *reserved) {
    LOGV("JNI_OnUnload");

    LuaJavaHelper::getInstance()->onUnload(vm);

    LuaJavaHelper::releaseInstance();
}